Many computing systems support multiple threads executing concurrently to perform tasks in parallel. During execution, the threads may require access to shared resources to perform certain functions. To handle contention between the threads, the computing systems may use semaphore data structures, which may coordinate the threads' access to the shared resources. The semaphore data structure may enable a thread to wait (e.g., sleep) for a resource while another thread is occupying the resource. Once the resource becomes available, the semaphore data structure may awaken the thread and provide the thread access to the resource.